home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
glass
/
glass.lha
/
GLASS
/
tm
/
tmgram.y
< prev
next >
Wrap
Text File
|
1990-11-02
|
6KB
|
283 lines
%{
/* file: tmgram.y
A YACC grammar for Miranda algebraic datatypes
*/
#include "tmdefs.h"
#include <ctype.h>
#include <tmc.h>
#include "tmds.h"
#include "tmstring.h"
#include "debug.h"
#include "tmerror.h"
#include "tmglobal.h"
#include "tmlex.h"
#include "tmmisc.h"
extern void setlexfile();
#define YYDEBUG 1 /* allow compilation of debugging code */
ds_list ans;
%}
%union {
ds pards;
ds_list pardslist;
constructor parcons;
constructor_list parconslist;
field parfield;
field_list parfieldlist;
char *parstring;
}
%token BAR
%token COLCOLEQ
%token EQEQ
%token COLON
%token COMMA
%token <parstring> NAME
%token SEMI
%token LSBRAC
%token RSBRAC
%token LRBRAC
%token RRBRAC
%start top
%type <pardslist> typelist
%type <pards> type
%type <parconslist> constructorlist
%type <parcons> constructor
%type <parfieldlist> tuplebody
%type <parfieldlist> fieldlist
%type <parfield> field
%type <parstring> typename
%type <parstring> consname
%type <parstring> elmname
%%
top:
typelist { ans = $1; }
typelist:
/* empty */ { $$ = new_ds_list(); }
| typelist type { app_ds_list( $1, $2 ); $$ = $1; }
;
type:
typename COLCOLEQ constructorlist SEMI
{
ckconstructor( $1, $3 );
$$ = new_DsCons( $1, $3 );
}
| typename EQEQ LRBRAC tuplebody RRBRAC SEMI
{
cktuple( $1, $4 );
$$ = new_DsTuple( $1, $4 );
}
| error SEMI
{
$$ = new_DsCons( new_string( "" ), new_constructor_list() );
}
;
tuplebody:
field
{
$$ = new_field_list();
app_field_list( $$, $1 );
}
| tuplebody COMMA field
{
app_field_list( $1, $3 );
$$ = $1;
}
;
constructorlist:
constructor
{
$$ = new_constructor_list();
app_constructor_list( $$, $1 );
}
| constructorlist BAR constructor
{
app_constructor_list($1, $3);
$$ = $1;
}
;
constructor:
consname fieldlist
{
$$ = new_constructor($1, $2);
}
;
fieldlist:
/* empty */ { $$ = new_field_list(); }
| fieldlist field { app_field_list($1, $2); $$ = $1; }
;
field:
elmname COLON NAME { $$ = new_field( 0, $1, $3 ); }
| elmname COLON LSBRAC NAME RSBRAC { $$ = new_field( 1, $1, $4 ); }
;
typename:
NAME { cktypename( $1 ); $$ = $1; }
;
consname:
NAME { ckconsname( $1 ); $$ = $1; }
;
elmname:
NAME { ckelmname( $1 ); $$ = $1; }
;
%%
static void yyerror( s )
char *s;
{
s = s; /* to stop complaints about unused arguments */
(void) sprintf( errpos, "%s(%d)", dsfilename, dslineno );
error( SYNTAXERR );
}
/* Check a name on underscores and give an error message if one is found */
static void ckunderscore( s )
char *s;
{
if( index( s, '_' ) != NULL ){
(void) sprintf( errpos, "%s(%d)", dsfilename, dslineno );
(void) strcpy( errarg, s );
error( NOUNDERSCORE );
}
}
/* Ensure that name 's' is a proper constructor name. */
static void ckconsname( s )
char *s;
{
if( s[0] == '\0' ) return;
ckunderscore( s );
if( !isupper( s[0] ) ){
(void) sprintf( errpos, "%s(%d)", dsfilename, dslineno );
(void) strcpy( errarg, s );
error( BADCONSNM );
}
}
/* Ensure that name 's' is a proper type name. */
static void cktypename( s )
char *s;
{
if( s[0] == '\0' ) return;
ckunderscore( s );
if( !islower( s[0] ) ){
(void) sprintf( errpos, "%s(%d)", dsfilename, dslineno );
(void) strcpy( errarg, s );
error( BADTYPENM );
}
}
/* Ensure that name 's' is a proper element name. */
static void ckelmname( s )
char *s;
{
if( s[0] == '\0' ) return;
ckunderscore( s );
}
/* Ensure that there are no double names in tuple with name 'nm'
* and fields 'fields'.
*/
static void cktuple( nm, fields )
string nm;
field_list fields;
{
register unsigned int ix; /* index of currently checked field */
register unsigned int iy; /* index of searched subsequent fields */
field fx; /* checked field */
field fy; /* searched field */
string fnm; /* name of currently checked field */
for( ix=0; ix<fields->sz; ix++ ){
fx = fields->arr[ix];
fnm = fx->sename;
iy = ix+1;
for( iy=ix+1; iy<fields->sz; iy++ ){
fy = fields->arr[iy];
if( strcmp( fy->sename, fnm ) == 0 ){
(void) sprintf( errpos, "in type '%s'", nm );
(void) sprintf( errarg, "'%s'", fnm );
error( DOUBLEFIELD );
}
}
}
}
/* Ensure that there are no double names in each of the constructors of
* constructor type with name 'nm' and constructors 'cons'.
*/
static void ckconstructor( nm, cons )
string nm;
constructor_list cons;
{
constructor conx;
constructor cony;
field_list fields;
register unsigned int cix; /* index in constructor list */
register unsigned int ix; /* index of currently checked field */
register unsigned int six; /* index for searching of fields/constr. */
field fx; /* checked field */
field fy; /* searched field */
string fnm; /* name of currently checked field */
string connm; /* name of current constructor */
for( cix=0; cix<cons->sz; cix++ ){
conx = cons->arr[cix];
fields = conx->confields;
connm = conx->conname;
for( six=cix+1; six<cons->sz; six++ ){
cony = cons->arr[six];
if( strcmp( cony->conname, connm ) == 0 ){
(void) sprintf( errpos, "in type '%s'", nm );
(void) sprintf( errarg, "'%s'", connm );
error( DOUBLECONS );
}
}
for( ix=0; ix<fields->sz; ix++ ){
fx = fields->arr[ix];
fnm = fx->sename;
six = ix+1;
for( six=ix+1; six<fields->sz; six++ ){
fy = fields->arr[six];
if( strcmp( fy->sename, fnm ) == 0 ){
(void) sprintf(
errpos,
"in type '%s', constructor '%s'",
nm,
connm
);
(void) sprintf( errarg, "'%s'", fnm );
error( DOUBLEFIELD );
}
}
}
}
}
/* top level of parser. */
ds_list parse( f )
FILE *f;
{
setlexfile( f );
(void) yyparse();
return( ans );
}